package com.ruoyi.iot.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.ruoyi.common.constant.CacheConstants;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.iot.domain.*;
import com.ruoyi.iot.mapper.IotRuleMapper;
import com.ruoyi.iot.mapper.IotRulesActionMapper;
import com.ruoyi.iot.mapper.IotRulesTriggerMapper;
import com.ruoyi.iot.mapper.IotRulesTriggerTermMapper;
import com.ruoyi.iot.service.IIotRuleService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;

/**
 * 联动规则Service业务层处理
 *
 * @author ruoyi
 * @date 2025-03-28
 */
@Slf4j
@Service
public class IotRuleServiceImpl implements IIotRuleService {
    @Autowired
    private IotRuleMapper iotRuleMapper;

    @Autowired
    private IotRulesTriggerMapper iotRulesTriggerMapper;

    @Autowired
    private IotRulesTriggerTermMapper iotRulesTriggerTermMapper;

    @Autowired
    private IotRulesActionMapper iotRulesActionMapper;

    @Resource
    private EKuiperRuleGeneratorService eKuiperRuleGeneratorService;

    @Autowired
    private RedisCache redisCache;

    @Autowired
    private IotEKuiperService iotEKuiperService;

    /**
     * 查询联动规则
     *
     * @param ruleId 联动规则主键
     * @return 联动规则
     */
    @Override
    public IotRule selectIotRuleByRuleId(Long ruleId) {
        return iotRuleMapper.selectIotRuleByRuleId(ruleId);
    }

    /**
     * 查询联动规则列表
     *
     * @param iotRule 联动规则
     * @return 联动规则
     */
    @Override
    public List<IotRule> selectIotRuleList(IotRule iotRule) {
        return iotRuleMapper.selectIotRuleList(iotRule);
    }

    /**
     * 新增联动规则
     *
     * @param iotRule 联动规则
     * @return 结果
     */
    @Override
    public int insertIotRule(IotRule iotRule) {
        iotRule.setCreateTime(DateUtils.getNowDate());
        return iotRuleMapper.insertIotRule(iotRule);
    }

    /**
     * 修改联动规则
     *
     * @param iotRule 联动规则
     * @return 结果
     */
    @Override
    public int updateIotRule(IotRule iotRule) {
        iotRule.setUpdateTime(DateUtils.getNowDate());
        return iotRuleMapper.updateIotRule(iotRule);
    }

    /**
     * 批量删除联动规则
     *
     * @param ruleIds 需要删除的联动规则主键
     * @return 结果
     */
    @Override
    public int deleteIotRuleByRuleIds(Long[] ruleIds) {
        return iotRuleMapper.deleteIotRuleByRuleIds(ruleIds);
    }

    /**
     * 删除联动规则信息
     *
     * @param ruleId 联动规则主键
     * @return 结果
     */
    @Override
    public int deleteIotRuleByRuleId(Long ruleId) {
        return iotRuleMapper.deleteIotRuleByRuleId(ruleId);
    }

    /**
     * 把规则同步到 EKuiper中
     *
     * @param ruleId 规则ID
     * @return R
     * @author Howe
     * @since 2025/6/9 15:14
     **/
    @Override
    public AjaxResult syncRuleToEKuiper(Long ruleId) {
        IotRule rule = iotRuleMapper.selectIotRuleByRuleId(ruleId);
        if (rule == null) {
            return AjaxResult.error("规则不存在");
        }
        IotRulesTrigger trigger = iotRulesTriggerMapper.selectIotRulesTriggerByRuleId(ruleId);
        if (trigger == null) {
            return AjaxResult.error("触发器不存在");
        }
        IotRulesTriggerTerm triggerTerm = new IotRulesTriggerTerm();
        triggerTerm.setTriggerId(trigger.getTriggerId());
        List<IotRulesTriggerTerm> triggerTerms = iotRulesTriggerTermMapper.selectIotRulesTriggerTermList(triggerTerm);

        // 动态生成流字段定义
        StringBuilder fields = new StringBuilder();
        for (IotRulesTriggerTerm term : triggerTerms) {
            IotProductAttributeModel iotProductAttributeModel = redisCache
                    .getCacheObject(CacheConstants.ATTRIBUTE_KEY + term.getAttributeId());
            if (iotProductAttributeModel == null) {
                return AjaxResult.error("属性不存在:AttributeId==>{}", term.getAttributeId());
            }
            term.setAttributeName(iotProductAttributeModel.getAttributeName());
            term.setAttributeCode(iotProductAttributeModel.getAttributeCode());
            // 拼接字段
            if (fields.length() > 0) fields.append(", ");
            fields.append(iotProductAttributeModel.getAttributeCode())
                    .append(" ")
                    .append(eKuiperRuleGeneratorService.mapAttributeTypeToEKuiperType(iotProductAttributeModel.getAttributeType()));
        }
        if (CollUtil.isEmpty(triggerTerms)) {
            return AjaxResult.error("触发项不存在");
        }
        IotRulesAction action = new IotRulesAction();
        action.setRuleId(ruleId);
        List<IotRulesAction> actions = iotRulesActionMapper.selectIotRulesActionList(action);
        if (CollUtil.isEmpty(actions)) {
            return AjaxResult.error("执行动作不存在");
        }
        trigger.setTriggerTerms(triggerTerms);
        rule.setIotRulesTrigger(trigger);
        rule.setActions(actions);
        String sqlContent = eKuiperRuleGeneratorService.generateEKuiperSql(rule);
        // 生成 actions 的对象数组
        List<Map<String, Object>> actionsContent = eKuiperRuleGeneratorService.generateEKuiperActionsList(actions);
        // 自动创建流
        String streamName = "mqtt_topic_" + rule.getRuleId();
        String streamFields = "data STRUCT(" + fields.toString() + ")";
        deleteRuleAndStream(new Long[]{ruleId});
        iotEKuiperService.createStreamIfNotExists(streamName, streamFields, streamName);
        return AjaxResult.success(iotEKuiperService.createRule(rule.getName(), sqlContent, actionsContent));
    }


    /**
     * 创建联动规则并同步在 eKuiper 创建流
     */
    @Override
    public int createRuleAndStream(IotRule iotRule) {
        // 1. 先创建本地规则
        int result = insertIotRule(iotRule);
        // 2. 自动同步创建 eKuiper 流
        // 假设流名为 mqtt_topic_{ruleId}，字段和 topic 需根据实际业务调整
        String streamName = "mqtt_topic_" + iotRule.getRuleId();
        String fields = "deviceId BIGINT, serviceId STRING, serviceName STRING, serviceParams STRING";
        iotEKuiperService.createStreamIfNotExists(streamName, fields, streamName);
        return result;
    }

    /**
     * 删除联动规则并同步在 eKuiper 删除流
     */
    @Override
    public int deleteRuleAndStream(Long[] ruleIds) {
        int result = deleteIotRuleByRuleIds(ruleIds);
        // 同步删除 eKuiper 流
        for (Long ruleId : ruleIds) {
            String streamName = "mqtt_topic_" + ruleId;
            iotEKuiperService.deleteStreamIfExists(streamName);
        }
        return result;
    }

}
